import './App.css';
import MyHeader from './components/Header/index.jsx';
import AddInput from './components/AddInput/index.jsx';
import TodoItem from './components/TodoItem/index.jsx';
import CheckModal from './components/Modal/CheckModal/index.jsx';
import EditModal from './components/Modal/EditModal/index.jsx';
import NoDataTip from './components/NoDataTip/index.jsx';

import React, { useState, useCallback, useEffect } from 'react';

function App() {
  const [todoList, setTodoList] = useState([]);
  const [isInputShow, setInputShow] = useState(false);
  const [isShowCheckModal, setShowCheckModal] = useState(false);
  const [isShowEditModal, setShowEditModal] = useState(false);
  //点击某一项的 查看 当前的data
  const [currentData, setCurrentData] = useState({});

  //区域一：父组件APP定义的方法----------------------------------------

  //功能：点击 '+' 图标显示输入框
  const showInputFn = () => {
    setInputShow(!isInputShow);
  };

  //区域二：父组件绑定事件`useCallback包裹`传递给子组件-------------------

  //功能：新增输入框内容到待办事件列表里
  //useCallback钩子第二个参数数组依赖项一旦由更变时会执行一次
  //数组依赖项 缓存一个被缓存的元素
  //该钩子避免子组件随着父组件的更新而频繁更新
  //缓存整个addItemFn函数，避免app组件render执行时生成新的函数传递给子组件里，子组件发现新的函数数据变化重新执行render重复更新
  const addItemFn = useCallback(
    (inputValue) => {
      // console.log(inputValue);
      //来自子组件传递过来的输入框输入内容

      //组装一个item对象
      const dataItem = {
        id: new Date().getTime(),
        content: inputValue,
        completed: false,
      };

      //将item 'push' -> concat 到数组里
      setTodoList((todoList) => [...todoList, dataItem]);

      // console.log(todoList);

      //隐藏输入框
      setInputShow(false);
    },
    //注意：这里的依赖项数组为什么不用填写依赖项？
    //因为上面setTodoList()的参数里是一个回调函数(todoList) => [...todoList, dataItem],且该函数的参数todoList作为useCallback的依赖项，所以不用填写到数组里
    []
  );

  //功能：点击某项查看按钮显示查看事件模态框
  //id: 接收子组件传递过来的id
  //缓存整个openCheckModal函数，避免app组件render执行时生成新的函数传递给子组件里，子组件发现新的函数数据变化重新执行render重复更新
  const openCheckModal = useCallback(
    (id) => {
      //将过滤后的data对象，即某一项的data数据 更新到currentData数据里
      //todoList.filter(item => item.id === id)返回的是一个数组
      //读取数组的第0位的数组元素
      setCurrentData(() => todoList.filter((item) => item.id === id)[0]);

      //点击查看显示模态框
      setShowCheckModal(true);
    },
    //注意：如果setCurrentData()里面的函数没有参数作为依赖项时，需要填写依赖项
    [todoList]
  );

  //功能：点击某些编辑按钮显示编辑模态框
  const openEditModal = useCallback(
    (id) => {
      setCurrentData(() => todoList.filter((item) => item.id === id)[0]);

      //点击查看编辑事件模态框
      setShowEditModal(true);
    },
    [todoList]
  );

  //功能：点击编辑事件模态框里面的确定按钮触发提交更改编辑表单内容
  //参数1：修改后的数据对象
  //参数2：原来的时间戳
  const submitEdit = useCallback((newData, id) => {
    setTodoList((todoList) =>
      todoList.map((item) => {
        //证明当前项是正在修改的那一项
        if (item.id === id) {
          item = newData;
        }
        return item;
      })
    );

    //关闭编辑事件模态框
    setShowEditModal(false);
  }, []);

  //功能：点击某项复选框按钮触发 同步复选框的状态和事件完成中横线显示
  //不依赖外部的任何数据
  const completedItem = useCallback((id) => {
    setTodoList((todoList) =>
      todoList.map((item) => {
        if (item.id === id) {
          item.completed = !item.completed;
        }
        return item;
      })
    );
  }, []);

  //功能：点击某项删除按钮 删除列表某一项待办事件
  const removeItem = useCallback((id) => {
    setTodoList((todoList) => todoList.filter((item) => item.id !== id));
  }, []);

  //区域三：副作用------------------------------------------------------

  //功能：从localStorage中获取todoData数据
  useEffect(() => {
    //从localStorage获取todoData数据
    const todoData = JSON.parse(localStorage.getItem('todoData') || '[]');

    //更改todoList为todoData数组
    setTodoList(todoData);
  }, []);

  //功能：将列表数据缓存到localStorage
  //依赖项：每当todoList数据变更时才会执行useEffect程序
  useEffect(() => {
    //保存todoList到localStorage里
    localStorage.setItem('todoData', JSON.stringify(todoList));
  }, [todoList]);

  return (
    <div className="App">
      {/* 查看事件模态框 */}
      <CheckModal
        isShowCheckModal={isShowCheckModal}
        data={currentData}
        closeModal={() => setShowCheckModal(false)}
      ></CheckModal>
      {/* 编辑事件模态框 */}
      <EditModal
        isShowEditModal={isShowEditModal}
        data={currentData}
        submitEdit={submitEdit}
      ></EditModal>
      {/* 应用标题 */}
      <MyHeader showInputFn={showInputFn} isInputShow={isInputShow}></MyHeader>
      {/* 添加事件输入框 */}
      <AddInput isInputShow={isInputShow} addItem={addItemFn}></AddInput>
      {/* 事件列表 如果没有数据渲染 NoDataTip组件 有数据渲染ul*/}
      {!todoList || todoList.length === 0 ? (
        <NoDataTip></NoDataTip>
      ) : (
        <ul className="todo-list">
          {todoList.map((item, index) => {
            return (
              <TodoItem
                data={item}
                key={index}
                openCheckModal={openCheckModal}
                openEditModal={openEditModal}
                completedItem={completedItem}
                removeItem={removeItem}
              ></TodoItem>
            );
          })}
        </ul>
      )}
    </div>
  );
}

export default App;
